
package gui.model;

import java.io.Serializable;

/**
 *
 * @author JtR
 */
public class DrinkModel implements Serializable {
    private static DrinkModel instance;
    public static DrinkModel getInstance() {
        if(instance == null)
            instance = new DrinkModel();
        return instance;
    }
    
    private Drink drink;
    private Coffee coffee;
    private Tea tea;
    private Size size;
    private Bean bean;
    private int temperature, brewTime;
    private boolean hazelnut, caramel, milk;
    
    /////////////
    // SETTERS //
    /////////////
    public void setDrink(Drink drink) {
        if(this.drink != drink) {
            reset();
            this.drink = drink;
        }
    }

    public void setCoffee(Coffee coffee) {
        if(this.coffee != coffee) {
            reset(Value.DRINK);
            this.coffee = coffee;
        }
    }

    public void setTea(Tea tea) {
        if(this.tea != tea) {
            reset(Value.DRINK);
            this.tea = tea;
        }
    }

    
    public void setSize(Size size) {
        if(this.size != size) {
            reset(Value.DRINK, Value.COFFEE, Value.TEA);
            this.size = size;
        }
    }

    public void setBean(Bean bean) {
        if(this.bean != bean) {
            reset(Value.DRINK, Value.COFFEE, Value.SIZE);
            this.bean = bean;
        }
    }

    public void setTemperature(int temperature) {
        this.temperature = temperature;
    }

    public void setBrewTime(int brewTime) {
        this.brewTime = brewTime;
    }

    public void setHazelnut(boolean hazelnut) {
        this.hazelnut = hazelnut;
    }

    public void setMilk(boolean milk) {
        this.milk = milk;
    }

    public void setCaramel(boolean caramel) {
        this.caramel = caramel;
    }

    
    /////////////
    // GETTERS //
    /////////////
    public Drink getDrink() {
        return drink;
    }

    public Coffee getCoffee() {
        return coffee;
    }

    public Tea getTea() {
        return tea;
    }

    public Size getSize() {
        return size;
    }

    public Bean getBean() {
        return bean;
    }

    public int getTemperature() {
        return temperature;
    }

    public int getBrewTime() {
        return brewTime;
    }

    public boolean isHazelnut() {
        return hazelnut;
    }

    public boolean isMilk() {
        return milk;
    }

    public boolean isCaramel() {
        return caramel;
    }
        
    public DrinkRepresantation getDrinkRepresentation() {
        return new DrinkRepresantation(drink, bean, coffee, tea, size, milk, caramel, hazelnut, temperature, brewTime);
    }
    
    private DrinkModel() {
        reset();
    }
    
    public void reset(Value... exceptions) {
        if(!arrayContains(exceptions, Value.DRINK))
            drink = null;
        
        if(!arrayContains(exceptions, Value.COFFEE))
            coffee = null;
        
        if(!arrayContains(exceptions, Value.TEA))
            tea = null;
        
        if(!arrayContains(exceptions, Value.SIZE))
            size = null;
        
        if(!arrayContains(exceptions, Value.BEAN))
            bean = null;
        
        if(!arrayContains(exceptions, Value.ADDITIONS)) {
            hazelnut = false;
            caramel = false;
            milk = false;
            temperature = 0;
            brewTime = 0;
        }
    }
    
    public enum Value {
        DRINK,
        COFFEE,
        TEA,
        SIZE,
        BEAN,
        ADDITIONS
    }
    
    public enum Drink {
        COFFEE,
        TEA
    }
    
    public enum Coffee {
        BLACK_COFFEE,
        CAPPUCHINO,
        ESPRESSO
    }
    
    public enum Tea {
        GREEN_TEA,
        BLACK_TEA,
        FRUIT_TEA
    }
    
    public enum Size {
        SMALL,
        MEDIUM,
        BIG
    }
    
    public enum Bean {
        ARABICA,
        ROBUSTA
    }
    
    public boolean arrayContains(Object[] array, Object value) {
        for(Object o : array) {
            if(o.equals(value))
                return true;
        }
        return false;
    }
    
    public void setToRepresntation(DrinkRepresantation rep) {
        drink = rep.drink;
        bean = rep.bean;
        coffee = rep.coffee;
        tea = rep.tea;
        size = rep.size;
        milk = rep.milk;
        caramel = rep.caramel;
        hazelnut = rep.hazelnut;
        temperature = rep.temperature;
        brewTime = rep.brewTime;
    }
    
    public class DrinkRepresantation implements Serializable {
        private Drink drink;
        private Bean bean;
        private Coffee coffee;
        private Tea tea;
        private Size size;
        private boolean milk, caramel, hazelnut;
        private int temperature, brewTime;

        public DrinkRepresantation(Drink drink, Bean bean, Coffee coffee, Tea tea, Size size, boolean milk, boolean caramel, boolean hazelnut, int temperature, int brewTime) {
            this.drink = drink;
            this.bean = bean;
            this.coffee = coffee;
            this.tea = tea;
            this.size = size;
            this.milk = milk;
            this.caramel = caramel;
            this.hazelnut = hazelnut;
            this.temperature = temperature;
            this.brewTime = brewTime;
        }

        public Drink getDrink() {
            return drink;
        }

        public Bean getBean() {
            return bean;
        }

        public Coffee getCoffee() {
            return coffee;
        }

        public Tea getTea() {
            return tea;
        }

        public Size getSize() {
            return size;
        }

        public boolean isMilk() {
            return milk;
        }

        public boolean isCaramel() {
            return caramel;
        }

        public boolean isHazelnut() {
            return hazelnut;
        }

        public int getTemperature() {
            return temperature;
        }

        public int getBrewTime() {
            return brewTime;
        }
        
        @Override
        public String toString() {
            StringBuilder b = new StringBuilder();
            switch(drink) {
                case COFFEE:
                    if(coffee == Coffee.ESPRESSO) {
                        b.append("Espresso");
                    } else {
                        if(coffee == Coffee.BLACK_COFFEE) {
                            b.append("Kaffee");
                        } else {
                            b.append("Cappuccino");
                        }
                        if(bean == Bean.ARABICA) {
                            b.append("(Arabica)");
                        } else {
                            b.append("(Robusta)");
                        }
                    }
                    
                    if(milk || caramel || hazelnut) {
                        b.append(" mit");
                        if(milk)
                            b.append(" Milch");
                        if(caramel)
                            b.append(" Karamell");
                        if(hazelnut)
                            b.append(" Haselnuss");
                    }
                    break;
                case TEA:
                    if(tea == Tea.BLACK_TEA) {
                        b.append("Schwarzer Tee ");
                    } else if(tea == Tea.FRUIT_TEA) {
                        b.append("Früchtetee ");
                    } else {
                        b.append("Grüner Tee ");
                    }
                    
                    b.append(brewTime);
                    b.append("min bei ");
                    b.append(temperature);
                    b.append("°C");
                    break;
                default:
                    throw new AssertionError(drink.name());
            }
                    
            if(size == Size.SMALL) {
                b.append(", klein");
            } else if(size == Size.MEDIUM) {
                b.append(", mittel");
            } else {
                b.append(", groß");
            }
            
            return b.toString();
        }
    }
}